package hotel.callback.oversea.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import hotel.base.oversea.utils.*;
import hotel.callback.oversea.config.service.RedisService;
import hotel.callback.oversea.entity.meituan.*;
import hotel.callback.oversea.mapper.*;
import hotel.callback.oversea.service.MtHotelOrderNotifyCallbackService;
import hotel.base.oversea.constant.CallbackConstants;
import hotel.base.oversea.constant.CommonConstants;
import hotel.base.oversea.constant.CommonUrlConstants;
import hotel.base.oversea.constant.MeituanConstants;
import hotel.base.oversea.constant.enums.MessageEnums;
import hotel.base.oversea.constant.enums.MtGoodsEnums;
import hotel.base.oversea.constant.enums.MtHotelEnums;
import hotel.base.oversea.dto.meituan.MtHotelGoodsBreakfastVo;
import hotel.base.oversea.vo.BatchPushRoomDatasVo;
import hotel.base.oversea.vo.RoomDataEntityVO;
import hotel.base.oversea.vo.RoomPriceVo;
import hotel.base.oversea.vo.RoomStatusInventory;
import hotel.base.oversea.vo.meituan.request.goods.MtHotelGoodsStatusDetailBaseCallbackVo;
import hotel.base.oversea.vo.meituan.request.goods.MtHotelGoodsStatusDetailCallbackVo;
import hotel.base.oversea.vo.meituan.response.goods.MtHotelGoodsCallbackVo;
import hotel.base.oversea.vo.meituan.response.goods.MtHotelGoodsPriceBaseDetailVo;
import hotel.base.oversea.vo.meituan.response.goods.MtHotelGoodsStatusCallbackVo;
import hotel.callback.oversea.service.MtHotelCheckGoodsPriceService;
import hotel.callback.oversea.service.MtHotelGoodsService;
import hotel.callback.oversea.service.MtHotelService;
import hotel.callback.oversea.vo.meituan.MtHotelInfoStatusCallbackVo;
import hotel.callback.oversea.vo.meituan.MtHotelInfoStatusContentCallbackVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 美团酒店信息Controller
 * @author qiuyy
 * @date 2020-05-15
 */
@Slf4j
@RestController
@RequestMapping("/mtHotelOrderNotify")
@Api(value = "MtHotelOrderNotifyController", tags = {"美团酒店订单接口"})
public class MtHotelOrderNotifyCallbackController {
    @Autowired
    private MtHotelCheckGoodsPriceService mtHotelCheckGoodsPriceService;
    @Autowired
    private MtHotelGoodsInfoHhbNotifyLogMapper mtHotelGoodsInfoHhbNotifyLogMapper;
    @Autowired
    private MtHotelGoodsStatusNotifyLogMapper mtHotelGoodsStatusNotifyLogMapper;
    @Autowired
    private MtHotelGoodsStatusHhbNotifyLogMapper mtHotelGoodsStatusHhbNotifyLogMapper;
    @Autowired
    private MtHotelGoodsChangePriceInterceptMapper mtHotelGoodsChangePriceInterceptMapper;
    @Autowired
    private MtHotelGoodsChangeStatusInterceptMapper mtHotelGoodsChangeStatusInterceptMapper;
    @Autowired
    private MtHotelService mtHotelService;
    @Autowired
    private MtHotelGoodsService mtHotelGoodsService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedisService redisService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private MtHotelOrderNotifyCallbackService mtHotelOrderNotifyCallbackService;
    /**
     *
     *
     * 携程接口限制 1秒9次，所以暂时存入缓存，由定时器处理多线程调用
     *
     * 产品状态：
     * 0 满房
     * 1 可预订
     * 2 不可预订
     * 3 不展示
     * @param request
     * @return
     */
    @PostMapping("/roomCallback")
    @ApiOperation(value = "美团房态消息通知",notes="必须经过auth授权")
    public ResultMt<Object> roomCallback(HttpServletRequest request){
        //开关
        if(null != redisTemplate.opsForValue().get(CallbackConstants.CLOSE_MT_CB_STATUS)){
            return new ResultMt<>("成功",0);
        }
        String result = getStrRequest(request);

        if(!StringUtils.isEmpty(result)){
            //分析数据结构，判断是否为比对后的售卖房型，不是则remove，再加入缓存
            String data = JSON.parseObject(result).getString("data");
            String method = JSON.parseObject(result).getString("method");
            String mt_accesskey = JSON.parseObject(result).getString("accesskey");
            String mt_signature = JSON.parseObject(result).getString("signature");
            String mt_nonce = JSON.parseObject(result).getString("nonce");
            String mt_timestamp = JSON.parseObject(result).getString("timestamp");
            if(!MtHotelEnums.apiMethodEnum.METHOD_HOTEL_ROOM_CALLBACK.getMethod().equals(method)){
                log.error("/////////////////  roomCallback 订单房态变更通知接收异常，上游method不匹配，需立即排查 ： "+data);
                return new ResultMt<>("请求参数为空",0);
            }
            MtHotelGoodsStatusCallbackVo vo = null;
            try {
                vo = JSON.parseObject(data, MtHotelGoodsStatusCallbackVo.class);
            }catch (Exception e){
                log.error(e.getMessage(),e);
            }
            if(null == vo){
                log.error(">>>>>>>>  roomCallback  房态异步通知，请求数据转化异常 result："+result);
            }
            /*String existResult = (String)redisTemplate.opsForValue().get(GsonUtils.GsonString(vo.getRsList()));
            if(null != existResult){
                return new ResultMt<>("成功",0);
            }
            redisTemplate.opsForValue().set(GsonUtils.GsonString(vo.getRsList()),"1",2,TimeUnit.SECONDS);*/

            //1、更新美团库表产品房态变更信息
            dealRoomStateDataEnd(vo,result, MtGoodsEnums.goodsChangeSource.NOTICE_STATUS.getCode(),mt_accesskey,mt_nonce,mt_timestamp,mt_signature);
        }else{
            log.error("/////////////////  roomCallback 订单房态变更通知接收异常，请求参数为空");
            return new ResultMt<>("请求参数为空",0);
        }
        //log.info("{} >>>>>>> 美团房态消息通知 roomCallback  执行结束时间",DateUtil.now());
        //返回通知上游结果
        return new ResultMt();
    }
    public void dealRoomStateDataEnd(MtHotelGoodsStatusCallbackVo vo, String result, Integer logType, String mt_accesskey, String mt_nonce, String mt_timestamp, String mt_signature) {
        Date now = new Date();
        String today = DateUtil.format(now,"yyyy-MM-dd");
        String nowHourStr = hotel.base.oversea.utils.DateUtil.formatDate(now,"HH");
        String yestoday = hotel.base.oversea.utils.DateUtil.formatDate(hotel.base.oversea.utils.DateUtil.addDay(now,-1),"yyyy-MM-dd");
        log.info("dealRoomStateDataEnd进入");
        Long thisTimestamp=Long.valueOf(String.valueOf(System.currentTimeMillis())+String.valueOf(logType));
        if(null != vo){
            List<MtHotelGoodsStatusDetailCallbackVo> rsListManyGoodsAboutHotelStateData = vo.getRsList();//多goods - hotel  - statusList   1-1-多   以产品为单位多条，多条可能为同一个酒店或不同酒店
            //List<MtHotelGoodsStatusDetailCallbackVo> manyGoodsAboutHotelRsListIsSaleRoom = new ArrayList<>();
            Map<Integer,List<MtHotelGoodsStatusDetailCallbackVo>>  manyHotelGoodsDataRelationMap = new HashMap<>();
            if(null != rsListManyGoodsAboutHotelStateData && rsListManyGoodsAboutHotelStateData.size()>0){
                if(logType== MtGoodsEnums.goodsChangeSource.NOTICE_HHB_STATUS.getCode()){
                    //很好办异步推送房态为不可预订，遍历
                    for (MtHotelGoodsStatusDetailCallbackVo oneGoodsStatusAboutHotelVo:rsListManyGoodsAboutHotelStateData){//每遍历一组为：  goods - hotel  - statusList   1-1-多
                        String oneGoodsExistJSON = (String)redisTemplate.opsForValue().get(GsonUtils.GsonString(oneGoodsStatusAboutHotelVo));
                        if(null != oneGoodsExistJSON){
                            continue;
                        }
                        redisTemplate.opsForValue().set(oneGoodsExistJSON,"1",1,TimeUnit.DAYS);

                        Integer thisGoodsId = oneGoodsStatusAboutHotelVo.getGoodsId();
                        Integer thisHotelId  = oneGoodsStatusAboutHotelVo.getHotelId();
                        Boolean existSaleHotel = redisService.isMember(CommonConstants.SWITCH_SALE_HOTEL_TO_PRICE_LIST,thisHotelId);
                        if(existSaleHotel){
                            if(null != thisHotelId && null != thisGoodsId){
                                //对比缓存校验是否售卖房型
                                String existSale = null;
                                existSale = (String)redisService.hmGet(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE,thisHotelId+"_"+thisGoodsId);
                                if(!ObjectUtils.isEmpty(existSale)){
                                    //log.info("异步 进入第二版 判断上架产品：thisGoodsId={},thisGoodsSwExsiRoomId={}",thisGoodsId,existSale);
                                }else{
                                    existSale = (String)redisService.get(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE+thisHotelId+"_"+thisGoodsId);
                                    //log.info("异步 进入第一版 判断上架产品：thisGoodsId={},thisGoodsSwExsiRoomId={}",thisGoodsId,existSale);
                                }
                                if(null != existSale){
                                    List<MtHotelGoodsStatusDetailCallbackVo> thisHotelGoodsData = manyHotelGoodsDataRelationMap.get(thisHotelId);
                                    if(null == thisHotelGoodsData || thisHotelGoodsData.size()==0){
                                        thisHotelGoodsData = new ArrayList<>();
                                    }
                                    thisHotelGoodsData.add(oneGoodsStatusAboutHotelVo);
                                    manyHotelGoodsDataRelationMap.put(thisHotelId,thisHotelGoodsData);
                                }else{
                                    //log.info("房态：未通过缓存校验");
                                }
                            }
                        }

                    }
                }else{
                    //美团推送房态 遍历
                    for (MtHotelGoodsStatusDetailCallbackVo oneGoodsStatusAboutHotelVo:rsListManyGoodsAboutHotelStateData){//每遍历一组为：  goods - hotel  - statusList   1-1-多
                        Integer thisGoodsId = oneGoodsStatusAboutHotelVo.getGoodsId();
                        Integer thisHotelId  = oneGoodsStatusAboutHotelVo.getHotelId();
                        Boolean existSaleHotel = redisService.isMember(CommonConstants.SWITCH_SALE_HOTEL_TO_PRICE_LIST,thisHotelId);
                        if(existSaleHotel){
                            if(null != thisHotelId && null != thisGoodsId){
                                //对比缓存校验是否售卖房型
                                String existSale = null;//(String)redisService.get(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE+String.valueOf(thisHotelId)+"_"+String.valueOf(thisGoodsId));
                                existSale = (String)redisService.hmGet(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE,thisHotelId+"_"+thisGoodsId);
                                if(!ObjectUtils.isEmpty(existSale)){
                                    //log.info("异步 进入第二版 判断上架产品：thisGoodsId={},thisGoodsSwExsiRoomId={}",thisGoodsId,existSale);
                                }else{
                                    existSale = (String)redisService.get(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE+thisHotelId+"_"+thisGoodsId);
                                    //log.info("异步 进入第一版 判断上架产品：thisGoodsId={},thisGoodsSwExsiRoomId={}",thisGoodsId,existSale);
                                }

                                if(null != existSale){
                                    //manyGoodsAboutHotelRsListIsSaleRoom.add(oneGoodsStatusAboutHotelVo);

                                    List<MtHotelGoodsStatusDetailCallbackVo> thisHotelGoodsData = manyHotelGoodsDataRelationMap.get(thisHotelId);
                                    if(null == thisHotelGoodsData || thisHotelGoodsData.size()==0){
                                        thisHotelGoodsData = new ArrayList<>();
                                    }
                                    thisHotelGoodsData.add(oneGoodsStatusAboutHotelVo);
                                    manyHotelGoodsDataRelationMap.put(thisHotelId,thisHotelGoodsData);
                                }else{
                                    //log.info("房态：未通过缓存校验");
                                }
                            }
                        }

                    }
                }

                //遍历每一家酒店 符合为售卖房型的 房态变更进行保存至缓存
                if(null != manyHotelGoodsDataRelationMap && manyHotelGoodsDataRelationMap.size()>0){
                    LinkedHashMap<Integer, List<Integer>> hotelMap= new LinkedHashMap<Integer, List<Integer>>();
                    log.info("当前批次变更通知，存在符合售卖房型的房态变更通知数据: hotelGoodsDataRelationMap.size={},result={}",manyHotelGoodsDataRelationMap.size());
                    //redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_NOTIFY_GOODS_STATE_CHANGE_MANY_HOTEL,JSON.toJSONString(manyHotelRsListIsSaleRoom));


                    String dingStampList = "";
                    //遍历多个酒店
                    for (Map.Entry<Integer,List<MtHotelGoodsStatusDetailCallbackVo>> entry:manyHotelGoodsDataRelationMap.entrySet()){
                        String thisTimestampApi = StringUtil.getTimestampRandom(thisTimestamp);
                        Integer thisHotelId = entry.getKey();

                        ////////////////////////判断异步通过date和当前酒店所属天数  start  //////////////////////////////////////
                        Map<String,String> disDaysMap = mtHotelGoodsService.findUpDateMap(thisHotelId,nowHourStr);
                        ////////////////////////判断异步通过date和当前酒店所属天数  end  //////////////////////////////////////


                        List<MtHotelGoodsStatusDetailCallbackVo> oneHotelGoodsData = entry.getValue();

                        Integer thisHotelCompare = 0;

                        //为上架产品的变化数据保存到缓存队列
                        //redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_NOTIFY_GOODS_STATE_CHANGE_MANY_HOTEL,JSON.toJSONString(oneHotelGoodsData));

                        //version 20200827 qyy  加进去队列为一个酒店的所有产品数据 保存为BatchPushRoomDatasVo的json字符串
                        //构建携程接口要求参数：每一家酒店的产品数据 List<RoomDataEntityVO>
                        List<RoomDataEntityVO> oneHotelAboutAllChangeGoodsVoSwitchsApi = new ArrayList<>();//构建数据 BatchPushRoomDatasVo.RoomDataEntityList 一个酒店的所有变化产品listVo，酒店vo所有变化了的产品信息
                        List<Integer> oneHotelGoodsIds = new ArrayList<>();//数据库日志集合
                        String notPushGoodsInfo = "";
                        //遍历当前该酒店产品
                        Map<String,Map<String,String>> thisHotelAllGoodsExsiNotSaleRoomMap = new HashMap();//key = goodsId   value = monthstatus
                        for (MtHotelGoodsStatusDetailCallbackVo oneGoods:oneHotelGoodsData){
                            Map<String,String> thisHotelOneGoodsOneDataExsiNotSaleRoomMap = new HashMap();
                            RoomDataEntityVO oneChangeGoodsSwitchsApi = new RoomDataEntityVO();
                            oneChangeGoodsSwitchsApi.setGoodId(oneGoods.getGoodsId());//当前产品id
                            oneChangeGoodsSwitchsApi.setRoomPrices(null);//当前产品所有多组价格日期集合--》当前为房态异步推送方法，该参数设置null
                            oneChangeGoodsSwitchsApi.setGoodInventory(1);
                            List<MtHotelGoodsStatusDetailBaseCallbackVo> oneGoodsDateStatusMonth = oneGoods.getGoodsStatuses();

                            List<RoomStatusInventory> thisGoodsRoomStatusInventoryList = null;
                            if(null != oneGoodsDateStatusMonth){
                                thisGoodsRoomStatusInventoryList = new ArrayList<>();
                                if(logType== MtGoodsEnums.goodsChangeSource.NOTICE_HHB_STATUS.getCode()){
                                    //很好办异步推送
                                    for (MtHotelGoodsStatusDetailBaseCallbackVo status:oneGoodsDateStatusMonth){
                                        if(null == redisTemplate.opsForValue().get("CRHHB_NOROOM_"+thisHotelId+oneGoods.getHotelId()+oneGoods.getGoodsId()+status.getDate())){
                                            redisTemplate.opsForValue().set("CRHHB_NOROOM_"+thisHotelId+oneGoods.getHotelId()+oneGoods.getGoodsId()+status.getDate(),1,1,TimeUnit.DAYS);

                                            // version 20200929 调整  异步的都推送给携程，，保存标识到缓存主动的判断缓存存在则不修改
                                            RoomStatusInventory roomStatusInventory = new RoomStatusInventory();
                                            roomStatusInventory.setDate(status.getDate());
                                            roomStatusInventory.setGoodStatus(status.getStatus());
                                            thisGoodsRoomStatusInventoryList.add(roomStatusInventory);//追加入携程vo酒店所有变化产品集合中
                                            //当前某酒店的这一个产品的 一个月日期房态 转json字符串 失效时间为30秒保存到缓存，作为主动查询的变更校验，校验到异步短时间内同样的房态日期一个月有推送过来过，则主动那边不需要作为变更数据保存到缓存;不用保存到缓存但是要更新库表
                                            Long days = hotel.base.oversea.utils.DateUtil.dateDiff(hotel.base.oversea.utils.DateUtil.getCurrTime(),"day",status.getDate(),"yyyy-MM-dd");
                                            //用途给主动查询：美团推送价格，缓存标识，主动那边十分钟内不处理该产品（主动调的接口是缓存接口）
                                            String redisHotelGoodsKeyExpiDays = CallbackConstants.REDIS_KEY_CALLBACK_CHANGE_STATUS_HEAD+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate();
                                            redisTemplate.opsForValue().set(redisHotelGoodsKeyExpiDays,status.getStatus(),Math.abs(days)+2,TimeUnit.DAYS);
                                            String redisHotelGoodsKeyExpiMin = CallbackConstants.REDIS_KEY_CALLBACK_MT_STATUS_LAST_HEAD+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate();
                                            redisTemplate.opsForValue().set(redisHotelGoodsKeyExpiMin,"1",1,TimeUnit.MINUTES);//房态接口为缓存接口，主动查询到的房态不一定是最新房态，所以需要判断异步推送在最近十分钟内有推过则主动那边不做查询处理
                                        }
                                    }
                                }else{
                                    //美团异步推送
                                    for (MtHotelGoodsStatusDetailBaseCallbackVo status:oneGoodsDateStatusMonth) {

                                        //5天变成售卖4天
                                        String closeThisDateRedisNormal = (String)redisService.get("normal_close_this_date");//yyyy-MM-dd
                                        if(!ObjectUtils.isEmpty(closeThisDateRedisNormal)){
                                            //判断是否普通酒店
                                            Boolean isVip = redisService.isMember(CommonConstants.SWITCH_SALE_HOTEL_VIP,thisHotelId);
                                            if(!isVip){
                                                if(closeThisDateRedisNormal.equals(status.getDate())){
                                                    log.info("CALLBACK NORMAL 减少天售卖，从后递减 hotelId={},goodsId={},closeThisDateRedisNormal={},date={},state={}",thisHotelId,oneGoods.getGoodsId(),closeThisDateRedisNormal,status.getDate(),status);
                                                    status.setStatus(0);
                                                }
                                            }
                                        }else{
                                            String closeThisDateRedisVip = (String)redisService.get("vip_close_this_date");//yyyy-MM-dd
                                            if(!ObjectUtils.isEmpty(closeThisDateRedisVip)){
                                                //判断是否普通酒店
                                                Boolean isVip = redisService.isMember(CommonConstants.SWITCH_SALE_HOTEL_VIP,thisHotelId);
                                                if(isVip){
                                                    if(closeThisDateRedisVip.equals(status.getDate())){
                                                        log.info("CALLBACK VIP 减少天售卖，从后递减 hotelId={},goodsId={},closeThisDateRedisVip={},date={},state={}",thisHotelId,oneGoods.getGoodsId(),closeThisDateRedisVip,status.getDate(),status);
                                                        status.setStatus(0);
                                                    }
                                                }
                                            }
                                        }

                                        if(!StringUtils.isEmpty(disDaysMap.get(status.getDate()))){
                                            log.info("status 日期符合"+status.getDate());
                                            boolean todo = true;
                                            Integer againStatusRedis = (Integer)redisTemplate.opsForValue().get("mt_callback_status_value_again_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate());
                                            if(null != againStatusRedis){
                                                if(BigDecimal.valueOf(againStatusRedis).compareTo(new BigDecimal(status.getStatus()))==0){
                                                    todo = false;
                                                    log.info("{} 异步推送房态重复 againStatusRedis={},status={}",againStatusRedis,oneGoods.getGoodsStatuses());
                                                }else{
                                                    redisTemplate.opsForValue().set("mt_callback_status_value_again_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate(),status.getStatus(),1,TimeUnit.HOURS);
                                                }
                                            }else{
                                                redisTemplate.opsForValue().set("mt_callback_status_value_again_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate(),status.getStatus(),1,TimeUnit.HOURS);
                                            }

                                            if(todo){
                                                String compareTime = (String)redisService.get("compare_time_for_mt_callback_status_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate());//主动查询那边设置失效时间1h
                                                if(null != compareTime && status.getStatus()==1){//1小时后缓存失效，如果商家一个产品日期价格第二天才改动，当前compreantime已经为空，异步通知这边没有阻碍直接更新；主动有更新过才会加入时间缓存
                                                    Integer m = 5;
                                                    if(null != redisTemplate.opsForValue().get("compare_time_for_mt_callback_min")){
                                                        m = (Integer) redisTemplate.opsForValue().get("compare_time_for_mt_callback_min");
                                                    }
                                                    if(hotel.base.oversea.utils.DateUtil.dateDiff(compareTime,"min", hotel.base.oversea.utils.DateUtil.getCurrTime(),"yyyy-MM-dd HH:mm:ss")<=m){
                                                        //主动先查询到变化，这时候异步推送过来，比主动晚5分钟内合理
                                                        //由主动查询set，这边的set是针对于主动查询set过的的更新；主动查询比异步先找到变化数据才会set这个缓存（主动判断是否重复才知道变化）
                                                        redisTemplate.opsForValue().set("compare_time_for_mt_callback_status_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate(), hotel.base.oversea.utils.DateUtil.getCurrTime(),40,TimeUnit.MINUTES);
                                                    }else{
                                                        log.info("{} 异步推送房态数据已超时超过"+m+"分钟，compareTime={},info={}",thisTimestamp,compareTime,thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate());
                                                        MtHotelGoodsChangeStatusIntercept mtHotelGoodsChangeStatusIntercept = new MtHotelGoodsChangeStatusIntercept();
                                                        mtHotelGoodsChangeStatusIntercept.setId(StringUtil.getUUID()+String.valueOf(oneGoods.getGoodsId()).substring(0,4));
                                                        mtHotelGoodsChangeStatusIntercept.setCreateTime(new Date());
                                                        mtHotelGoodsChangeStatusIntercept.setMtHotelId(String.valueOf(thisHotelId));
                                                        mtHotelGoodsChangeStatusIntercept.setMtGoodsId(String.valueOf(oneGoods.getGoodsId()));
                                                        mtHotelGoodsChangeStatusIntercept.setMtDate(status.getDate());
                                                        mtHotelGoodsChangeStatusIntercept.setMtTimestamp(mt_timestamp);
                                                        mtHotelGoodsChangeStatusIntercept.setMtNonce(mt_nonce);
                                                        mtHotelGoodsChangeStatusIntercept.setMtAccesskey(mt_accesskey);
                                                        mtHotelGoodsChangeStatusIntercept.setMtSignature(mt_signature);
                                                        mtHotelGoodsChangeStatusIntercept.setMtStatus(status.getStatus());
                                                        try {
                                                            mtHotelGoodsChangeStatusInterceptMapper.insert(mtHotelGoodsChangeStatusIntercept);
                                                        }catch (Exception e){
                                                            log.error("mtHotelGoodsChangeStatusInterceptLogMapper.insert 保存异常");
                                                            e.printStackTrace();
                                                        }
                                                        todo = false;
                                                        notPushGoodsInfo+=oneGoods.getGoodsId()+"_"+status.getDate()+"_"+status.getStatus()+",";
                                                    }

                                                }
                                            }

                                            if(todo){

                                                if(status.getStatus()!=1){//不可预订的产品单独加入钉钉消息推送
                                                    //thisHotelOneGoodsOneDataExsiNotSaleRoomMap.put(status.getDate(),String.valueOf(status.getStatus()));
                                                    log.info("异步callback房态不可预订了推送thisHotelCompare=1hotelId={},goodsId={},date={}",thisHotelId,oneGoods.getGoodsId(),status.getDate());
                                                    thisHotelCompare = 1;
                                                }

                                                RoomStatusInventory roomStatusInventory = new RoomStatusInventory();
                                                roomStatusInventory.setDate(status.getDate());
                                                roomStatusInventory.setGoodStatus(status.getStatus());
                                                thisGoodsRoomStatusInventoryList.add(roomStatusInventory);//追加入携程vo酒店所有变化产品集合中
                                                //当前某酒店的这一个产品的 一个月日期房态 转json字符串 失效时间为30秒保存到缓存，作为主动查询的变更校验，校验到异步短时间内同样的房态日期一个月有推送过来过，则主动那边不需要作为变更数据保存到缓存;不用保存到缓存但是要更新库表
                                                Long days = hotel.base.oversea.utils.DateUtil.dateDiff(hotel.base.oversea.utils.DateUtil.getCurrTime(), "day", status.getDate(), "yyyy-MM-dd");
                                                //用途给主动查询：美团推送价格，缓存标识，主动那边十分钟内不处理该产品（主动调的接口是缓存接口）
                                                String redisHotelGoodsKeyExpiDays = CallbackConstants.REDIS_KEY_CALLBACK_CHANGE_STATUS_HEAD+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate();
                                                redisTemplate.opsForValue().set(redisHotelGoodsKeyExpiDays,status.getStatus(),Math.abs(days)+2,TimeUnit.DAYS);
                                                String redisHotelGoodsKeyExpiMin = CallbackConstants.REDIS_KEY_CALLBACK_MT_STATUS_LAST_HEAD+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+status.getDate();
                                                redisTemplate.opsForValue().set(redisHotelGoodsKeyExpiMin,"1",1,TimeUnit.MINUTES);
                                            }
                                        }
                                    }
                                }
                            }
                            if(null != thisGoodsRoomStatusInventoryList && thisGoodsRoomStatusInventoryList.size()>0){

                                if(null != thisHotelOneGoodsOneDataExsiNotSaleRoomMap && thisHotelOneGoodsOneDataExsiNotSaleRoomMap.size()>0){
                                    thisHotelAllGoodsExsiNotSaleRoomMap.put(String.valueOf(oneGoods.getGoodsId()),thisHotelOneGoodsOneDataExsiNotSaleRoomMap);//不可预订的这一个产品的日历房态
                                }

                                oneChangeGoodsSwitchsApi.setRoomStatusInventorys(thisGoodsRoomStatusInventoryList);//当前产品的房态集合（一个月）

                                oneHotelAboutAllChangeGoodsVoSwitchsApi.add(oneChangeGoodsSwitchsApi);//追加入携程vo酒店所有变化产品集合中

                                oneHotelGoodsIds.add(oneGoods.getGoodsId());
                            }

                            //数据库日志----------------start  所有都保存
                            List<MtHotelGoodsStatusDetailBaseCallbackVo> goodsStatuses = oneGoods.getGoodsStatuses();
                            int i = 0;
                            for (MtHotelGoodsStatusDetailBaseCallbackVo base:goodsStatuses){
                                if(!StringUtils.isEmpty(disDaysMap.get(base.getDate()))){
                                    if(logType== MtGoodsEnums.goodsChangeSource.NOTICE_HHB_STATUS.getCode()){
                                        try{
                                            MtHotelGoodsStatusHhbNotifyLog mtHotelGoodsStatusHhbNotifyLog = new MtHotelGoodsStatusHhbNotifyLog();
                                            mtHotelGoodsStatusHhbNotifyLog.setId(StringUtil.getUUID());
                                            if(i == 0){
                                                //mtHotelGoodsStatusHhbNotifyLog.setRemark(now+key+"："+result);
                                            }
                                            mtHotelGoodsStatusHhbNotifyLog.setMtHotelId(String.valueOf(thisHotelId));
                                            mtHotelGoodsStatusHhbNotifyLog.setMtGoodsId(String.valueOf(oneGoods.getGoodsId()));
                                            mtHotelGoodsStatusHhbNotifyLog.setMtDate(base.getDate());
                                            mtHotelGoodsStatusHhbNotifyLog.setMtStatus(base.getStatus());
                                            mtHotelGoodsStatusHhbNotifyLog.setState(0);
                                            mtHotelGoodsStatusHhbNotifyLog.setCreateTime(new Date());
                                            mtHotelGoodsStatusHhbNotifyLog.setModifyTime(mtHotelGoodsStatusHhbNotifyLog.getCreateTime());
                                            try {
                                                mtHotelGoodsStatusHhbNotifyLogMapper.insert(mtHotelGoodsStatusHhbNotifyLog);
                                            }catch (Exception e){
                                                log.info("保存失败 mtHotelGoodsStatusHhbNotifyLogMapper.insert 274");
                                                e.printStackTrace();
                                            }

                                            i+= 1;
                                        }catch (Exception e){
                                            log.error(" 很好办 房态异步通知  保存日志异常 {},{} ",e.getMessage(), JSON.toJSONString(oneHotelGoodsData));
                                            e.printStackTrace();
                                        }

                                    }else{
                                        try{
                                            MtHotelGoodsStatusNotifyLog mtHotelGoodsStatusNotifyLog = new MtHotelGoodsStatusNotifyLog();
                                            mtHotelGoodsStatusNotifyLog.setId(StringUtil.getUUID());
                                            if(i == 0){
                                                //mtHotelGoodsStatusNotifyLog.setRemark(now+key+"："+result);
                                            }
                                            mtHotelGoodsStatusNotifyLog.setMtHotelId(String.valueOf(thisHotelId));
                                            mtHotelGoodsStatusNotifyLog.setMtGoodsId(String.valueOf(oneGoods.getGoodsId()));
                                            mtHotelGoodsStatusNotifyLog.setMtDate(base.getDate());
                                            mtHotelGoodsStatusNotifyLog.setMtStatus(base.getStatus());
                                            mtHotelGoodsStatusNotifyLog.setState(0);
                                            mtHotelGoodsStatusNotifyLog.setCreateTime(new Date());
                                            mtHotelGoodsStatusNotifyLog.setAccesskey(mt_accesskey);
                                            mtHotelGoodsStatusNotifyLog.setNonce(mt_nonce);
                                            mtHotelGoodsStatusNotifyLog.setTimestamp(thisTimestampApi);//hhb的时间戳
                                            mtHotelGoodsStatusNotifyLog.setSignature(mt_signature);
                                            mtHotelGoodsStatusNotifyLog.setModifyTime(mtHotelGoodsStatusNotifyLog.getCreateTime());
                                            try {
                                                mtHotelGoodsStatusNotifyLogMapper.insert(mtHotelGoodsStatusNotifyLog);
                                            }catch (Exception e){
                                                log.info("保存失败 mtHotelGoodsStatusNotifyLogMapper.insert 300");
                                                e.printStackTrace();
                                            }
                                            i+= 1;
                                        }catch (Exception e){
                                            log.error(" 美团 房态异步通知  保存日志异常 {},{} ",e.getMessage(), JSON.toJSONString(oneHotelGoodsData));
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            }
                            //数据库日志----------------end

                        }

                        //异步线程   更新保存  房态 库表数据  多个产品 多组一个月日期房态
                        if(null != oneHotelAboutAllChangeGoodsVoSwitchsApi && oneHotelAboutAllChangeGoodsVoSwitchsApi.size()>0){
                            /*MtNotifyShortLog mtNotifyShortLog = new MtNotifyShortLog();
                            mtNotifyShortLog.setMtAccesskey(mt_accesskey);
                            mtNotifyShortLog.setMtSignature(mt_signature);
                            mtNotifyShortLog.setMtNonce(mt_nonce);
                            mtNotifyShortLog.setMtTimestamp(mt_timestamp);
                            mtNotifyShortLog.setId(StringUtil.getUUID());
                            mtNotifyShortLog.setTimestamp(thisTimestampApi);
                            mtNotifyShortLog.setCreateTime(new Date());
                            mtNotifyShortLog.setMtHotelId(String.valueOf(thisHotelId));
                            mtNotifyShortLog.setSwHotelId(null);
                            mtNotifyShortLog.setRemark(notPushGoodsInfo);
                            mtNotifyShortLog.setOprate(MtGoodsEnums.goodsChangeType.PUSH.getCode());//push
                            mtNotifyShortLog.setSource(logType); // 10 异步价格  11 主动查询价格 12 订单校验价格 13 很好办异步价格  20 异步房态  21 主动查询房态 23 很好办异步房态 30 携程推送成功数据
                            try {

                                mtNotifyShortLogMapper.insert(mtNotifyShortLog);

                            }catch (Exception e){
                                log.info("异步通知有变化数据保存日志mtNotifyShortLog异常 mtNotifyShortLog={}",JSON.toJSONString(mtNotifyShortLog));
                                e.printStackTrace();
                            }*/

                            //遍历完酒店产品变化的数据，携程接口参数结构，缓存队列
                            BatchPushRoomDatasVo oneHotelVoSwitchsApi = new BatchPushRoomDatasVo();
                            oneHotelVoSwitchsApi.setTimestamp(thisTimestampApi);
                            oneHotelVoSwitchsApi.setCompare(thisHotelCompare);
                            oneHotelVoSwitchsApi.setMtHotelId(Integer.valueOf(thisHotelId));//要推送的酒店一个
                            oneHotelVoSwitchsApi.setRoomDataEntityList(oneHotelAboutAllChangeGoodsVoSwitchsApi);//要推送的该酒店的产品信息集合（一个vo 包含 产品id 产品默认库存1 产品日期价格集合 产品日期房态集合）


                            String extThisTimestamp=thisTimestamp+"_"+ StringUtil.getFourRandom()+thisHotelId;
                            dingStampList += oneHotelVoSwitchsApi.getTimestamp()+"，";

                            //保存房态
                            //meituanSaveUpdateGoodsStatusTableOtherTask.executeSaveUpdateGoodsStatusTableOther(oneHotelAboutAllChangeGoodsVoSwitchsApi,String.valueOf(thisHotelId),extThisTimestamp);

                            if(null != thisHotelAllGoodsExsiNotSaleRoomMap && thisHotelAllGoodsExsiNotSaleRoomMap.size()>0){
                                //SendUtils.dingMsgNotLog("[call] 不可预订 ",hotel.base.oversea.utils.DateUtil.getCurrTime()+" 时间戳："+thisTimestampApi+" 酒店id："+thisHotelId+" 产品："+GsonUtils.GsonString(thisHotelAllGoodsExsiNotSaleRoomMap),MessageEnums.genre.MT_ROOM_FULL.getCode(),restTemplate);
                            }

                            //push到队列，每次一个酒店数据
                            pushQueueRoomStatus(logType,oneHotelVoSwitchsApi);

                            log.info("{} 异步房态通知push到缓存中 thisTimestampApiStatus={},oneHotelVoSwitchsApi={},redissize={}",thisTimestampApi, JSON.toJSONString(oneHotelVoSwitchsApi),redisTemplate.opsForList().size(MeituanConstants.REDIS_NOTIFY_GOODS_STATE_CHANGE_MANY_HOTEL));
                        }


                        //根据酒店，构建钉钉消息通知数据，接受完一组酒店的产品，putmap
                        if(null != oneHotelGoodsIds && oneHotelGoodsIds.size()>0){
                            hotelMap.put(thisHotelId,oneHotelGoodsIds);
                        }
                        //下一个酒店遍历
                        //..


                    }//结束所有酒店

                    //最后钉钉消息通知
                    if(null != hotelMap && hotelMap.size()>0){

                        String dingExist = (String)redisTemplate.opsForValue().get(JSON.toJSONString(hotelMap));
                        if(null == dingExist){
                            if(logType== MtGoodsEnums.goodsChangeSource.NOTICE_HHB_STATUS.getCode()){
                                log.info("很好办通知 房态变更 ding："+ JSON.toJSONString(hotelMap));
                                //SendUtils.dingMsgNotLog("【很好办通知-房态变更】",hotel.base.oversea.utils.DateUtil.getCurrTime()+" 时间戳："+dingStampList+"，内容"+ JSON.toJSONString(hotelMap),2,restTemplate);
                                redisTemplate.opsForValue().set(JSON.toJSONString(hotelMap),"1",5,TimeUnit.SECONDS);
                            }else{
                                log.info("美团异步通知 产品变更 ding："+ JSON.toJSONString(hotelMap));
                                //SendUtils.dingMsgNotLog("【美团异步通知-房态变更-人工关注】",hotel.base.oversea.utils.DateUtil.getCurrTime()+" 时间戳："+dingStampList+"，内容"+ JSON.toJSONString(hotelMap),2,restTemplate);
                                redisTemplate.opsForValue().set(JSON.toJSONString(hotelMap),"1",5,TimeUnit.SECONDS);
                            }
                        }
                    }
                }else{
                    log.info("无可处理的房态信息");
                    //log.info("房态异步通知 未匹配到售卖房型，当前批次房态变更数据不采纳");
                }
            }else{
                //log.error(">>>>>>>>  roomCallback  房态异步通知，请求数据rsList null，请求参数result："+result);
            }
        }else{
            log.error(">>>>>>>>  roomCallback  房态异步通知，请求数据params parse error，请求参数result："+result);
        }
    }
    /**
     * 将变更的酒店信息 push到队列，通知各个前端平台（携程前端，飞猪前端）
     */
    public void pushQueueRoomStatus(Integer logType, BatchPushRoomDatasVo oneHotelVoSwitchsApi){
        //push到队列，每次一个酒店数据
        if(logType== MtGoodsEnums.goodsChangeSource.NOTICE_HHB_STATUS.getCode()){
            redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_CHANGE_GOODS_DATA_MANY_HOTEL_HHB_CHANNEL, GsonUtils.GsonString(oneHotelVoSwitchsApi));
        }else{
            redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_CHANGE_GOODS_DATA_MANY_HOTEL, GsonUtils.GsonString(oneHotelVoSwitchsApi));
        }
        ////同时再push一份给飞猪，push到队列，每次一个酒店数据
        //redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_CHANGE_GOODS_DATA_MANY_HOTEL_FOR_FP,JSON.toJSONString(oneHotelVoSwitchsApi));
        //2020-10-31 直接同步调飞猪接口，保存时间戳日志
        if(null == redisService.get("push_fp_price_status_change_close")){
            /*Result result = RestTemplateUtils.post(CommonUrlConstants.FP_HOST+FpConstants.API_URL_FP_CALLBACK_PRICE_STATUS,GsonUtils.GsonString(oneHotelVoSwitchsApi),restTemplate);
            if(result.getCode() != CommonConstants.SUCCESS){
                SendUtils.dingMsgNotLog("[CALLBACK-FP-STATUS-ERRRO] 美团异步推飞猪房态异常 ", hotel.base.oversea.utils.DateUtil.getCurrTime()+" 接口返回："+GsonUtils.GsonString(result),MessageEnums.genre.GOODS_STATUS_AND_PRICE.getCode(),restTemplate);
            }*/

            redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_CHANGE_GOODS_DATA_MANY_HOTEL_FOR_FP, GsonUtils.GsonString(oneHotelVoSwitchsApi));
        }

    }

    /**
     *
     *
     * 携程接口限制 1秒9次，所以暂时存入缓存，由定时器处理多线程调用
     *
     * 上游推送产品变更通知，包含价格，取消规则，早餐等规则
     * 当前处理保存到缓存，不做处理，另外开启定时器处理
     * 上游毫秒级别推送，一有变更就推送
     *
     * 每次推送一家酒店的变更产品信息，已产品为单位 返回一次数据可能是多个酒店的某些产品
     *
     * @param request
     * @return
     */
    @PostMapping("/rpCallback")
    @ApiOperation(value = "美团产品规则变更通知",notes="必须经过auth授权")
    public ResultMt<Object> rpCallback(HttpServletRequest request){
        //"accesskey":"a6a02428da2c702188d7a8985fac24f6","signature":"sRWjCf62I9E79Bftr2IW0I8StlY=","partnerId":12734,"version":"1.0","nonce":1478396260,"timestamp":1591171318}
        //开关
        if(null != redisTemplate.opsForValue().get(CallbackConstants.CLOSE_MT_CB_PRICE)){
            return new ResultMt<>("成功",0);
        }

        //log.info(">>>>>>>> rpCallback 美团产品规则变更通知 执行开始时间: {}",now);
        String result = getStrRequest(request);
        //notify的数据是以产品为单位的，list 的产品属于不同酒店
        if(!StringUtils.isEmpty(result)){
            List<MtHotelGoodsCallbackVo> goods = null;
            String data = JSON.parseObject(result).getString("data");
            String method = JSON.parseObject(result).getString("method");
            String mt_accesskey = JSON.parseObject(result).getString("accesskey");
            String mt_signature = JSON.parseObject(result).getString("signature");
            String mt_nonce = JSON.parseObject(result).getString("nonce");
            String mt_timestamp = JSON.parseObject(result).getString("timestamp");
            if(!MtHotelEnums.apiMethodEnum.METHOD_HOTEL_GOODS_CALLBACK.getMethod().equals(method)){
                log.error("订单产品规则变更通知接收异常，上游method不匹配，需立即排查 ： "+result);
                return new ResultMt<>("成功",0);
            }
            if(StringUtils.isEmpty(data)){
                //log.error("美团产品规则变更通知 data null: {}",cn.hutool.core.date.DateUtil.now(),result);
                return new ResultMt<>("成功",0);
            }
            String goodsStr = JSON.parseObject(data).getString("goods");
            if(StringUtils.isEmpty(goodsStr)){
                log.error("美团产品规则变更通知 goods null: {}", DateUtil.now(),result);
                return new ResultMt<>("成功",0);
            }

           /* String existResult = (String)redisTemplate.opsForValue().get(goodsStr);
            if(null != existResult){
                return new ResultMt<>("成功",0);
            }
            redisTemplate.opsForValue().set(goodsStr,"1",2,TimeUnit.SECONDS);
*/
            try{
                goods = JSON.parseArray(goodsStr, MtHotelGoodsCallbackVo.class);
            }catch (Exception e){
                log.error("美团产品规则变更通知 data parse error:{}",result);
                log.error(e.getMessage(),e);
            }
            dealGoodsPriceEndV2(goods,result, MtGoodsEnums.goodsChangeSource.NOTICE_PRICE.getCode(),mt_accesskey,mt_nonce,mt_signature,mt_timestamp);
        }else{
            log.error("/////////////////  rpCallback 美团产品规则变更通知接收异常，请求参数为空");
            return new ResultMt<>("请求参数为空",0);
        }

        //log.info(">>>>>>>> rpCallback 美团产品规则变更通知 执行结束时间: {}",DateUtil.now());
        return new ResultMt();
    }
    public void dealGoodsPriceEndV2(List<MtHotelGoodsCallbackVo> goods, String result, Integer logType, String mt_accesskey, String mt_nonce, String mt_signature, String mt_timestamp){
        log.info("进入dealGoodsPriceEndV2");
        String now = DateUtil.now();
        String hourStr = hotel.base.oversea.utils.DateUtil.formatDate(now,"HH");
        String todayOrYest = hotel.base.oversea.utils.DateUtil.formatDate(now,"yyyy-MM-dd");
        Long thisTimestamp=Long.valueOf(String.valueOf(System.currentTimeMillis())+String.valueOf(logType));
        if(null != goods && goods.size()>0){
            Map<String,List<MtHotelGoodsCallbackVo>> valiHotelGoodsDataMap = new HashMap<>();//多个酒店，每个酒店多条产品数据
            for (MtHotelGoodsCallbackVo v:goods){
                String thisHotelId = v.getHotelId();
                Boolean existSaleHotel = redisService.isMember(CommonConstants.SWITCH_SALE_HOTEL_TO_PRICE_LIST,Integer.valueOf(thisHotelId));
                if(existSaleHotel){
                    if(null != thisHotelId){
                        List<MtHotelGoodsCallbackVo> thisHotelGoodsValiList = valiHotelGoodsDataMap.get(thisHotelId);
                        if(thisHotelGoodsValiList != null && thisHotelGoodsValiList.size()>0){
                        }else{
                            thisHotelGoodsValiList = new ArrayList<>();
                        }
                        String thisGoodsId = v.getGoodsId();
                        if(null != thisGoodsId){
                            //对比缓存校验是否售卖房型
                            String existSale = null;//(String)redisService.get(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE+String.valueOf(thisHotelId)+"_"+String.valueOf(thisGoodsId));

                            existSale = (String)redisService.hmGet(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE,thisHotelId+"_"+thisGoodsId);
                            if(!ObjectUtils.isEmpty(existSale)){
                                //log.info("异步 进入第二版 判断上架产品：thisGoodsId={},thisGoodsSwExsiRoomId={}",thisGoodsId,existSale);
                            }else{
                                existSale = (String)redisService.get(CommonConstants.SWITCH_SELLING_THE_HOUSE_TYPE+thisHotelId+"_"+thisGoodsId);
                                //log.info("异步 进入第一版 判断上架产品：thisGoodsId={},thisGoodsSwExsiRoomId={}",thisGoodsId,existSale);
                            }
                            if(null != existSale){
                                thisHotelGoodsValiList.add(v);
                                valiHotelGoodsDataMap.put(thisHotelId,thisHotelGoodsValiList);
                            }else{
                                log.info("未通过缓存校验");
                            }
                        }
                    }
                }

            }
            if(null != valiHotelGoodsDataMap && valiHotelGoodsDataMap.size()>0){

                log.info("当前批次变更通知，存在符合售卖房型的产品规则变更通知数据 valiHotelGoodsDataMap.size(): {},result=:{}",valiHotelGoodsDataMap.size());
                try{

                    LinkedHashMap<String, Map> hotelDingPriceChangeMap= new LinkedHashMap<String, Map>();
                    List<MtHotelGoodsInfoNotifyLog> saveGoodsInfoNotifyLogArray = new ArrayList<>();
                    List<MtHotelGoodsInfoHhbNotifyLog> saveGoodsInfoNotifyLogArrayHhb = new ArrayList<>();
                    String dingStampList = "";
                    for (Map.Entry<String,List<MtHotelGoodsCallbackVo>> goodsDataEntry:valiHotelGoodsDataMap.entrySet()){
                        String thisTimestampApi = StringUtil.getTimestampRandom(thisTimestamp);//Long.valueOf(String.valueOf(thisTimestamp)+StringUtil.timestampIndexId(thisTimestamp,redisTemplate));
                        String thisHotelId = goodsDataEntry.getKey();

                        ////////////////////////判断异步通过date和当前酒店所属天数  start  //////////////////////////////////////
                        Map<String,String> disDaysMap = mtHotelGoodsService.findUpDateMap(Integer.valueOf(thisHotelId),hourStr);
                        ////////////////////////判断异步通过date和当前酒店所属天数  end  //////////////////////////////////////

                        Integer thisHotelCompare = 0;
                        List<MtHotelGoodsCallbackVo> oneHotelGoodsDataList = goodsDataEntry.getValue();

                        //redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_NOTIFY_GOODS_CHANGE_MANY_HOTEL,JSON.toJSONString(thisGoodsDataList));//每次放进去的是属于一个酒店的产品数据，携程批量修改价格接口需要为同一个酒店的产品List

                        //version 20200827 qyy  加进去队列为一个酒店的所有产品数据 保存为BatchPushRoomDatasVo的json字符串
                        List<RoomDataEntityVO> oneHotelAboutAllChangeGoodsVoSwitchsApi = new ArrayList<>();//构建数据 BatchPushRoomDatasVo 一个酒店vo-所有变化产品listVo，酒店vo所有变化了的产品信息
                        Map thisHotelGoodsMap = new HashMap();
                        Map<String, List<MtHotelGoodsBreakfastVo>> putBreakfastMap = new HashMap<>();
                        String notPushGoodsInfo = "";

                        for (MtHotelGoodsCallbackVo oneGoods:oneHotelGoodsDataList){
                            //一个酒店多个产品，遍历每个产品

                            //构建携程接口要求参数：每一家酒店的产品数据 List<RoomDataEntityVO>
                            RoomDataEntityVO oneChangeGoodsSwitchsApi = new RoomDataEntityVO();
                            oneChangeGoodsSwitchsApi.setGoodId(Integer.valueOf(oneGoods.getGoodsId()));//当前产品id
                            oneChangeGoodsSwitchsApi.setRoomStatusInventorys(null);//当前产品所有多组房态日期集合--》当前为价格异步推送方法，该参数设置null
                            oneChangeGoodsSwitchsApi.setGoodInventory(1);
                            List<MtHotelGoodsPriceBaseDetailVo> oneGoodsDatePriceMonth = oneGoods.getPriceModels();
                            if(null != oneGoodsDatePriceMonth && oneGoodsDatePriceMonth.size()>0){
                                List<RoomPriceVo> changeOneGoodsDatePriceListBuildSwitchsVo = new ArrayList<>();//重构携程接口对象，当前该产品的多组变化价格日期数据集合list
                                for (MtHotelGoodsPriceBaseDetailVo thisGoodsOneChangePriceDate:oneGoodsDatePriceMonth){//遍历美团返回的每个产品的日期价格数据,每次一个日期的变化价格
                                    //构建当前产品的每个价格日期vo，加入list  // version 20200929 调整  异步的都推送给携程，，保存标识到缓存主动的判断缓存存在则不修改
                                    if(!StringUtils.isEmpty(disDaysMap.get(thisGoodsOneChangePriceDate.getDate()))){

                                        log.info("thisGoodsOneChangePriceDate日期符合"+thisGoodsOneChangePriceDate.getDate());
                                        boolean todo = true;

                                        Integer againPriceRedis = (Integer)redisTemplate.opsForValue().get("mt_callback_price_value_again_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate());
                                        if(null != againPriceRedis){
                                            if(BigDecimal.valueOf(againPriceRedis).compareTo(new BigDecimal(thisGoodsOneChangePriceDate.getSalePrice()))==0){
                                                log.info("{} 异步推送价格重复 againStatusRedis={},salePrice={}",againPriceRedis,thisGoodsOneChangePriceDate.getSalePrice());
                                                todo = false;
                                            }else{
                                                redisTemplate.opsForValue().set("mt_callback_price_value_again_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate(),thisGoodsOneChangePriceDate.getSalePrice(),1,TimeUnit.HOURS);
                                            }
                                        }else{
                                            redisTemplate.opsForValue().set("mt_callback_price_value_again_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate(),thisGoodsOneChangePriceDate.getSalePrice(),1,TimeUnit.HOURS);
                                        }
                                        if(todo){
                                            //mtHotelGoodsChangePriceInterceptMapper 针对于 主动查询查到了，异步晚通知的情况。如果晚通知在主动查询查到的5分钟内，
                                            // 还可以push到队列，超出了5分钟不给push到队列，增加携程接口压力
                                            String compareTime = (String)redisService.get("compare_time_for_mt_callback_price_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate());//主动查询那边设置失效时间1h
                                            if(null != compareTime){//1小时后缓存失效，如果商家一个产品日期价格第二天才改动，当前compreantime已经为空，异步通知这边没有阻碍直接更新；主动有更新过才会加入时间缓存
                                                //会进来的数据为  美团异步通知 在一个小时内 频繁变动的美团酒店产品 （记录至频繁变动日期表），， 且当下程序增加时间戳比对，该推送为上一次五分钟之内的推送则可push到队列
                                                String redisHotelGoodsKeyExpiDays = CallbackConstants.REDIS_KEY_CALLBACK_CHANGE_PRICE_HEAD+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate();
                                                Integer hasPrice = (Integer)redisService.get(redisHotelGoodsKeyExpiDays);
                                                if(null != hasPrice && BigDecimal.valueOf(hasPrice).compareTo(new BigDecimal(thisGoodsOneChangePriceDate.getSalePrice()))>0){//跌价才判断，涨价都给他，涨价我们要推送不然可能亏损
                                                    Integer m = 5;
                                                    if(null != redisTemplate.opsForValue().get("compare_time_for_mt_callback_min")){
                                                        m = (Integer) redisTemplate.opsForValue().get("compare_time_for_mt_callback_min");
                                                    }
                                                    //compare_time_for_mt_callback_price_ 由主动查询set，这边的set是针对于主动查询set过的的更新；主动查询比异步先找到变化数据才会set这个缓存（主动判断是否重复才知道变化）
                                                    if(hotel.base.oversea.utils.DateUtil.dateDiff(compareTime,"min", hotel.base.oversea.utils.DateUtil.getCurrTime(),"yyyy-MM-dd HH:mm:ss")<=m){
                                                        //主动先查询到变化，这时候异步推送过来，比主动晚5分钟内合理
                                                        redisTemplate.opsForValue().set("compare_time_for_mt_callback_price_"+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate(), hotel.base.oversea.utils.DateUtil.getCurrTime(),1,TimeUnit.HOURS);
                                                    }else{
                                                        log.info("{} 异步推送价格数据已超时超过"+m+"分钟，compareTime={},info={}",thisTimestamp,compareTime,thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate());
                                                        MtHotelGoodsChangePriceIntercept mtHotelGoodsChangePriceIntercept = new MtHotelGoodsChangePriceIntercept();
                                                        mtHotelGoodsChangePriceIntercept.setId(StringUtil.getUUID()+oneGoods.getGoodsId().substring(0,4));
                                                        mtHotelGoodsChangePriceIntercept.setCreateTime(new Date());
                                                        mtHotelGoodsChangePriceIntercept.setMtHotelId(thisHotelId);
                                                        mtHotelGoodsChangePriceIntercept.setMtGoodsId(oneGoods.getGoodsId());
                                                        mtHotelGoodsChangePriceIntercept.setMtDate(thisGoodsOneChangePriceDate.getDate());
                                                        mtHotelGoodsChangePriceIntercept.setMtTimestamp(mt_timestamp);
                                                        mtHotelGoodsChangePriceIntercept.setMtNonce(mt_nonce);
                                                        mtHotelGoodsChangePriceIntercept.setMtAccesskey(mt_accesskey);
                                                        mtHotelGoodsChangePriceIntercept.setMtSignature(mt_signature);
                                                        mtHotelGoodsChangePriceIntercept.setMtPrice(thisGoodsOneChangePriceDate.getSalePrice());
                                                        try {
                                                            mtHotelGoodsChangePriceInterceptMapper.dayInsert(hotel.base.oversea.utils.DateUtil.getCurrTime().split(" ")[0].replace("-",""),mtHotelGoodsChangePriceIntercept);
                                                        }catch (Exception e){
                                                            log.error("mtHotelGoodsChangePriceInterceptLogMapper.insert 保存异常");
                                                            e.printStackTrace();
                                                        }
                                                        todo = false;
                                                        notPushGoodsInfo +=oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate()+"_"+thisGoodsOneChangePriceDate.getSalePrice()+",";
                                                    }
                                                }
                                            }
                                        }
                                        Integer apiSalePrice = thisGoodsOneChangePriceDate.getSalePrice();
                                        Integer thisPriceOrLibrary = apiSalePrice;//当前价格

                                        if(todo){
                                            Map<String,Object> checkMap = mtHotelCheckGoodsPriceService.commonCheckOneGoodsDate(todayOrYest,thisGoodsOneChangePriceDate.getDate(),hourStr,result,thisTimestampApi,thisGoodsOneChangePriceDate, oneGoods,12);
                                            todo = (Boolean)checkMap.get("todo");
                                            if(!todo){
                                                continue;
                                            }
                                            thisHotelCompare = (Integer) checkMap.get("thisHotelCompare");
                                            thisPriceOrLibrary = (Integer) checkMap.get("thisPriceOrLibrary");
                                            String priceMemark = (String) checkMap.get("priceMemark");
                                            thisGoodsOneChangePriceDate.setPriceRemark(priceMemark);
                                        }
                                        if(todo){
                                            Integer subPrice = thisGoodsOneChangePriceDate.getSubPrice();

                                            //当前某酒店的这一个产品的 一个月日期价格 转json字符串 失效时间为30秒保存到缓存，作为主动查询的变更校验，校验到异步短时间内同样的价格日期一个月有推送过来过，则主动那边不需要作为变更数据保存到缓存;不用保存到缓存但是要更新库表
                                            Long days = hotel.base.oversea.utils.DateUtil.dateDiff(hotel.base.oversea.utils.DateUtil.getCurrTime(),"day",thisGoodsOneChangePriceDate.getDate(),"yyyy-MM-dd");
                                            ////用途给主动查询：美团推送价格，缓存标识，主动那边半小时内不处理该产品（主动调的接口是缓存接口）---》》》房态这样处理，，，价格不这样处理，价格不是缓存接口  callback_mt_push_hhb_change_price_data_hotelId +"_"+goodsId+"_"+date+"_"+priceOrStatus;
                                            String redisHotelGoodsKeyExpiDays = CallbackConstants.REDIS_KEY_CALLBACK_CHANGE_PRICE_HEAD+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate();
                                            redisTemplate.opsForValue().set(redisHotelGoodsKeyExpiDays,thisPriceOrLibrary,Math.abs(days)+2,TimeUnit.DAYS);//存的还是接口最新价格，不然如果存在的调整了的标准价，会一直判断到不同一直推送携程。
                                            String redisHotelGoodsKeyExpiMin = CallbackConstants.REDIS_KEY_CALLBACK_MT_PRICE_LAST_HEAD+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate();
                                            redisTemplate.opsForValue().set(redisHotelGoodsKeyExpiMin,"1",1,TimeUnit.MINUTES);//房态接口为缓存接口，主动查询到的房态不一定是最新房态，所以需要判断异步推送在最近十分钟内有推过则主动那边不做查询处理
                                            //设置佣金缓存 携程需要
                                            redisTemplate.opsForValue().set(CallbackConstants.REDIS_KEY_CALLBACK_SUB_PRICE_HEAD+thisHotelId+"_"+oneGoods.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate(),thisPriceOrLibrary+"_"+subPrice,Math.abs(days)+2, TimeUnit.DAYS);

                                            //是否调价酒店
                                            String ctrlPriceClose = (String)redisService.get("swmt_ctrl_price_hotels_close");
                                            if(ObjectUtils.isEmpty(ctrlPriceClose)){
                                                Integer tj = (Integer)redisService.hmGet(CommonConstants.SWITCH_JOIN_ACTIVE_HOTEL_LIST,Integer.valueOf(thisHotelId));
                                                if(!ObjectUtils.isEmpty(tj)){
                                                    thisPriceOrLibrary = BigDecimal.valueOf(thisPriceOrLibrary).add(BigDecimal.valueOf(tj)).intValue();
                                                    log.info("异步，最终价格，调价酒店，进行追加金额：hotelId={},tj={},thisPriceOrLibrary={}",thisHotelId,tj,thisPriceOrLibrary);
                                                    thisGoodsOneChangePriceDate.setPriceRemark(thisPriceOrLibrary+"_"+tj+"|"+thisGoodsOneChangePriceDate.getPriceRemark());
                                                }
                                            }
                                            String swPriceKey = CallbackConstants.REDIS_KEY_CALLBACK_CHANGE_PRICE_JOB+thisHotelId+"_"+thisGoodsOneChangePriceDate.getGoodsId()+"_"+thisGoodsOneChangePriceDate.getDate();;
                                            redisTemplate.opsForValue().set(swPriceKey,thisPriceOrLibrary,Math.abs(days)+2, TimeUnit.DAYS);//供检测功能使用

                                            RoomPriceVo thisGoodsThisOneDatePirceSwitchsVo = new RoomPriceVo();
                                            thisGoodsThisOneDatePirceSwitchsVo.setSalePrice(thisPriceOrLibrary);//推送的是最终真实推送价格不同于has保存的是产品调价前价格
                                            thisGoodsThisOneDatePirceSwitchsVo.setDate(thisGoodsOneChangePriceDate.getDate());
                                            thisGoodsThisOneDatePirceSwitchsVo.setSubPrice(thisGoodsOneChangePriceDate.getSubPrice());
                                            changeOneGoodsDatePriceListBuildSwitchsVo.add(thisGoodsThisOneDatePirceSwitchsVo);

                                        }
                                    }
                                }

                                if(null != changeOneGoodsDatePriceListBuildSwitchsVo && changeOneGoodsDatePriceListBuildSwitchsVo.size()>0){
                                    oneChangeGoodsSwitchsApi.setRoomPrices(changeOneGoodsDatePriceListBuildSwitchsVo);//当前产品所有多组价格日期集合

                                    oneHotelAboutAllChangeGoodsVoSwitchsApi.add(oneChangeGoodsSwitchsApi);//追加入携程vo酒店所有变化产品集合中

                                    //追加钉钉消息
                                    thisHotelGoodsMap.put(oneGoods.getGoodsId(),oneGoods.getGoodsName());
                                }
                            }

                            //每个产品对应早餐信息  v 2020-10-31 早餐暂时不根据异步推送，每天定时器主动查询一遍上架酒店的最新早餐信息
                           /* if (null != oneGoods.getBreakFast() && oneGoods.getBreakFast().size() > 0) {
                                //该上架酒店的上架产品 存在早餐信息，更新到缓存，失效时间两天（定时器每天推送一次早餐给携程飞猪）
                                //putBreakfastMap.put(thisHotelId+"_"+oneGoods.getGoodsId(),oneGoods.getBreakFast());//goodsId不是唯一所以要加上酒店id
                            }*/

                            //保存当前 酒店  的每一个产品日志
                            if(logType== MtGoodsEnums.goodsChangeSource.NOTICE_HHB_PRICE.getCode()){
                                List<MtHotelGoodsPriceBaseDetailVo> priceModels = oneGoods.getPriceModels();
                                if(null != priceModels && priceModels.size()>0){
                                    for (MtHotelGoodsPriceBaseDetailVo p:priceModels){
                                        MtHotelGoodsInfoHhbNotifyLog mtHotelGoodsInfoHhbNotifyLog = new MtHotelGoodsInfoHhbNotifyLog();
                                        mtHotelGoodsInfoHhbNotifyLog.setId(StringUtil.getUUID()+oneGoods.getGoodsId().substring(0,4));
                                        mtHotelGoodsInfoHhbNotifyLog.setMtHotelId(oneGoods.getHotelId());
                                        mtHotelGoodsInfoHhbNotifyLog.setMtGoodsId(oneGoods.getGoodsId());
                                        mtHotelGoodsInfoHhbNotifyLog.setMtGoodsName(oneGoods.getGoodsName());
                                        //mtHotelGoodsInfoHhbNotifyLog.setPriceModels(JSON.toJSONString(oneGoods.getPriceModels()));
                                        mtHotelGoodsInfoHhbNotifyLog.setState(0);
                                        mtHotelGoodsInfoHhbNotifyLog.setCreateTime(new Date());
                                        mtHotelGoodsInfoHhbNotifyLog.setModifyTime(mtHotelGoodsInfoHhbNotifyLog.getCreateTime());
                                        mtHotelGoodsInfoHhbNotifyLog.setPrice(p.getSalePrice());
                                        mtHotelGoodsInfoHhbNotifyLog.setDate(p.getDate());
                                        saveGoodsInfoNotifyLogArrayHhb.add(mtHotelGoodsInfoHhbNotifyLog);
                                    }
                                }

                            }else{
                                List<MtHotelGoodsPriceBaseDetailVo> priceModels = oneGoods.getPriceModels();
                                if(null != priceModels && priceModels.size()>0){
                                    for (MtHotelGoodsPriceBaseDetailVo p:priceModels){
                                        if(!StringUtils.isEmpty(disDaysMap.get(p.getDate()))){
                                            MtHotelGoodsInfoNotifyLog mtHotelGoodsInfoNotifyLog = new MtHotelGoodsInfoNotifyLog();
                                            mtHotelGoodsInfoNotifyLog.setId(StringUtil.getUUID()+oneGoods.getGoodsId().substring(0,4));
                                            mtHotelGoodsInfoNotifyLog.setMtHotelId(oneGoods.getHotelId());
                                            mtHotelGoodsInfoNotifyLog.setMtGoodsId(oneGoods.getGoodsId());
                                            mtHotelGoodsInfoNotifyLog.setMtGoodsName(oneGoods.getGoodsName());
                                            mtHotelGoodsInfoNotifyLog.setMtConfirmType(oneGoods.getConfirmType());
                                            mtHotelGoodsInfoNotifyLog.setMtGoodsType(oneGoods.getGoodsType());
                                            mtHotelGoodsInfoNotifyLog.setMtNeedRealTel(oneGoods.getNeedRealTel());
                                            //mtHotelGoodsInfoNotifyLog.setPriceModels(JSON.toJSONString(oneGoods.getPriceModels()));
                                            mtHotelGoodsInfoNotifyLog.setMtAveragePrice(oneGoods.getAveragePrice());
                                            //mtHotelGoodsInfoNotifyLog.setGoodsActivityMap(JSON.toJSONString(oneGoods.getGoodsActivityMap()));
                                            //mtHotelGoodsInfoNotifyLog.setBookRules(JSON.toJSONString(oneGoods.getBookRules()));
                                            //mtHotelGoodsInfoNotifyLog.setBreakFast(JSON.toJSONString(oneGoods.getBreakFast()));
                                            //mtHotelGoodsInfoNotifyLog.setCancelRules(JSON.toJSONString(oneGoods.getCancelRules()));
                                            //mtHotelGoodsInfoNotifyLog.setRoomInfoList(JSON.toJSONString(oneGoods.getRoomInfoList()));//2020-10-12 qyy 改为日志输出 表存储太大
                                            mtHotelGoodsInfoNotifyLog.setAccesskey(mt_accesskey);
                                            mtHotelGoodsInfoNotifyLog.setNonce(mt_nonce);
                                            mtHotelGoodsInfoNotifyLog.setTimestamp(thisTimestampApi);//(mt_timestamp);
                                            mtHotelGoodsInfoNotifyLog.setSignature(mt_signature);
                                            mtHotelGoodsInfoNotifyLog.setMtThirdParty(oneGoods.getThirdParty());
                                            mtHotelGoodsInfoNotifyLog.setMtGoodsStatus(oneGoods.getGoodsStatus());
                                            mtHotelGoodsInfoNotifyLog.setState(0);
                                            mtHotelGoodsInfoNotifyLog.setCreateTime(new Date());
                                            mtHotelGoodsInfoNotifyLog.setModifyTime(mtHotelGoodsInfoNotifyLog.getCreateTime());
                                            mtHotelGoodsInfoNotifyLog.setPrice(p.getSalePrice());
                                            mtHotelGoodsInfoNotifyLog.setRemark(p.getPriceRemark());//当存在全量推送时该字段有值
                                            mtHotelGoodsInfoNotifyLog.setDate(p.getDate());
                                            saveGoodsInfoNotifyLogArray.add(mtHotelGoodsInfoNotifyLog);
                                        }

                                    }
                                }
                            }
                        }

                        if(null != oneHotelAboutAllChangeGoodsVoSwitchsApi && oneHotelAboutAllChangeGoodsVoSwitchsApi.size()>0){
                            //遍历该完酒店产品，保存当前该酒店，部分变化的产品数据，携程接口参数结构，缓存队列

                            BatchPushRoomDatasVo oneHotelVoSwitchsApi = new BatchPushRoomDatasVo();
                            oneHotelVoSwitchsApi.setTimestamp(thisTimestampApi);
                            oneHotelVoSwitchsApi.setCompare(thisHotelCompare);
                            oneHotelVoSwitchsApi.setMtHotelId(Integer.valueOf(thisHotelId));//要推送的酒店一个
                            oneHotelVoSwitchsApi.setRoomDataEntityList(oneHotelAboutAllChangeGoodsVoSwitchsApi);//要推送的该酒店的产品信息集合（一个vo 包含 产品id 产品默认库存1 产品日期价格集合 产品日期房态集合）

                            dingStampList += oneHotelVoSwitchsApi.getTimestamp()+",";

                            //push到队列，每次一个酒店数据
                            pushQueueRoomPrice(logType,oneHotelVoSwitchsApi);

                            log.info("{} 异步价格通知push到缓存中 thisTimestampApiPrice={},oneHotelVoSwitchsApi={},redissize={}",thisTimestampApi, JSON.toJSONString(oneHotelVoSwitchsApi),redisTemplate.opsForList().size(MeituanConstants.REDIS_KEY_DEALING_NOTIFY_ROOM_INFO_JOB_PROCESS_ING));

                        }

                        //追加一个酒店的所有简化的变化产品信息 到钉钉消息map
                        if(null != thisHotelGoodsMap && thisHotelGoodsMap.size()>0){
                            hotelDingPriceChangeMap.put(thisHotelId,thisHotelGoodsMap);
                        }


                        //当前一个酒店接收到的变更商品的早餐信息：（早餐信息有值就默认为有变化）
                        /*if(null != putBreakfastMap && putBreakfastMap.size()>0){
                            log.info("saveDealGoodsFromJob putBreakfastMap size:{}",putBreakfastMap.size());
                            Map<String, List<MtHotelGoodsBreakfastVo>> redisMap = (Map<String, List<MtHotelGoodsBreakfastVo>>)redisService.get(SwitchConstants.REDIS_SWITCH_HOTEL_CHANGE_BREAKFAST);
                            if(null != redisMap && redisMap.size()>0){
                                redisMap.putAll(putBreakfastMap);
                            }else{
                                redisMap = putBreakfastMap;
                            }
                            //放到缓存，定时器每天凌晨跑一次
                            redisService.set(SwitchConstants.REDIS_SWITCH_HOTEL_CHANGE_BREAKFAST,redisMap);
                        }*/
                        //遍历 下一个酒店
                        //..



                    }//遍历完所有酒店的所有产品

                    //最后发送钉钉消息
                    if(null != hotelDingPriceChangeMap && hotelDingPriceChangeMap.size()>0){
                        String dingExist = (String)redisTemplate.opsForValue().get(JSON.toJSONString(hotelDingPriceChangeMap));
                        if(null == dingExist){
                            if(logType== MtGoodsEnums.goodsChangeSource.NOTICE_HHB_PRICE.getCode()){
                                log.info("很好办通知 产品变更价格发生变动 ding："+ JSON.toJSONString(hotelDingPriceChangeMap));
                                //SendUtils.dingMsgNotLog("【很好办通知-价格发生变动】", hotel.base.oversea.utils.DateUtil.getCurrTime()+" 时间戳："+dingStampList+" 内容"+ JSON.toJSONString(hotelDingPriceChangeMap),2,restTemplate);
                                redisTemplate.opsForValue().set(JSON.toJSONString(hotelDingPriceChangeMap),"1",5,TimeUnit.SECONDS);
                                if(null != saveGoodsInfoNotifyLogArrayHhb && saveGoodsInfoNotifyLogArrayHhb.size()>0){
                                    try{
                                        mtHotelGoodsInfoHhbNotifyLogMapper.insertList(saveGoodsInfoNotifyLogArrayHhb);
                                    }catch (Exception e){
                                        log.info("保存失败 爬虫推送mtHotelGoodsInfoHhbNotifyLogMapper.insertList 861");
                                        e.printStackTrace();
                                    }
                                }

                            }else{
                                log.info("美团异步通知 产品变更价格发生变动 ding："+ JSON.toJSONString(hotelDingPriceChangeMap));
                                //SendUtils.dingMsgNotLog("【美团异步通知-产品变更-价格发生变动-人工关注】", hotel.base.oversea.utils.DateUtil.getCurrTime()+" 时间戳："+dingStampList+"，内容"+ JSON.toJSONString(hotelDingPriceChangeMap),2,restTemplate);
                                redisTemplate.opsForValue().set(JSON.toJSONString(hotelDingPriceChangeMap),"1",5,TimeUnit.SECONDS);
                                if(null != saveGoodsInfoNotifyLogArray && saveGoodsInfoNotifyLogArray.size()>0){
                                    try{
                                        mtHotelOrderNotifyCallbackService.batchInsertList(hotel.base.oversea.utils.DateUtil.getCurrTime().split(" ")[0].replace("-",""),saveGoodsInfoNotifyLogArray);
                                    }catch (Exception e){
                                        log.info("保存失败 mtHotelGoodsInfoNotifyLogMapper.batchInsertList 874");
                                        e.printStackTrace();
                                    }
                                }

                            }
                        }
                    }
                }catch (Exception e){
                    log.error("///////////美团产品规则变更通知 保存日志异常：{}",e.getMessage());
                    e.printStackTrace();
                }
            }else{
                log.info("无可处理的产品变更信息");
                //log.info("///////////美团产品规则变更通知 未匹配到售卖房型，当前批次变更数据不采纳");
            }
        }else{
            log.error("美团产品规则变更通知 goodsinfo null 转化异常: {}", DateUtil.now(),result);
        }
    }
    /**
     * 将变更的酒店信息 push到队列，通知各个前端平台（携程前端，飞猪前端）
     */
    public void pushQueueRoomPrice(Integer logType, BatchPushRoomDatasVo oneHotelVoSwitchsApi){
        if(logType== MtGoodsEnums.goodsChangeSource.NOTICE_HHB_PRICE.getCode()){
            redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_CHANGE_GOODS_DATA_MANY_HOTEL_HHB_CHANNEL, JSON.toJSONString(oneHotelVoSwitchsApi));//每次放进去的是属于一个酒店的产品数据，携程批量修改价格接口需要为同一个酒店的产品List
        }else{
            redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_CHANGE_GOODS_DATA_MANY_HOTEL, JSON.toJSONString(oneHotelVoSwitchsApi));
        }
        ////同时再push一份给飞猪，push到队列，每次一个酒店数据
        //redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_CHANGE_GOODS_DATA_MANY_HOTEL_FOR_FP,JSON.toJSONString(oneHotelVoSwitchsApi));
        //2020-10-31 直接同步调飞猪接口，保存时间戳日志
        if(null == redisService.get("push_fp_price_status_change_close")){
            /*Result result = RestTemplateUtils.post(CommonUrlConstants.FP_HOST+ FpConstants.API_URL_FP_CALLBACK_PRICE_STATUS,GsonUtils.GsonString(oneHotelVoSwitchsApi),restTemplate);
            if(result.getCode() != CommonConstants.SUCCESS){
                SendUtils.dingMsgNotLog("[CALLBACK-FP-PRICE-ERRRO] 美团异步推飞猪'价格'异常 ", hotel.base.oversea.utils.DateUtil.getCurrTime()+" 接口返回："+GsonUtils.GsonString(result),MessageEnums.genre.GOODS_STATUS_AND_PRICE.getCode(),restTemplate);
            }*/
            redisTemplate.opsForList().leftPush(MeituanConstants.REDIS_CHANGE_GOODS_DATA_MANY_HOTEL_FOR_FP, GsonUtils.GsonString(oneHotelVoSwitchsApi));
        }

    }

    @PostMapping("/hotelCallback")
    @ApiOperation(value = "美团酒店变更通知",notes="必须经过auth授权")
    public ResultMt<Object> hotelCallback(HttpServletRequest request){
        /**
         * type 酒店信息变更类型：
         * 1 信息变化
         * 2 酒店下线
         * 3 酒店上线
         *
         * 信息变化：主动调用酒店详情接口更新酒店信息
         * 酒店下线：更新数据库酒店状态 为 state=0 异常
         * 酒店上线：更新数据库酒店状态 为 state=1 正常
         */
        String result = getStrRequest(request);

        String now = DateUtil.now();
        //requestSendDingMessage("[美团酒店变更通知]", now);
        log.info("/////////////////////////////酒店静态信息变更通知 执行时间 ： {}，{}",result,now);
        if(StringUtils.isEmpty(result)){
            log.error("/////////////////  hotelCallback 酒店静态信息变更通知接收异常，params null ： "+result);
            return new ResultMt<>("params null",-1);
        }
        String method = JSON.parseObject(result).getString("method");
        if(!MtHotelEnums.apiMethodEnum.METHOD_HOTEL_INFO_CALLBACK.getMethod().equals(method)){
            log.error("/////////////////  hotelCallback 酒店静态信息变更通知接收异常，上游method不匹配，需立即排查 ： "+result);
            return new ResultMt<>("method error",-1);
        }
        String data = JSON.parseObject(result).getString("data");
        if(StringUtils.isEmpty(data)){
            log.error("/////////////////  hotelCallback 酒店静态信息变更通知接收异常，data null ： "+result);
            return new ResultMt<>("data null",-1);
        }
        //{"method":"hotel.poi.change.callback","data":"{\"hotelList\":[{\"hotelId\":940421596,\"type\":2}]}","accesskey":"a6a02428da2c702188d7a8985fac24f6","signature":"peReQmugtqhGDC354ifdFok/TbU=","partnerId":12734,"version":"1.0","nonce":1478396260,"timestamp":1591171318}
        MtHotelInfoStatusCallbackVo hotelData = JSON.parseObject(data, MtHotelInfoStatusCallbackVo.class);
        if(null == hotelData || null == hotelData.getHotelList() || hotelData.getHotelList().size()==0){
            log.error("/////////////////  hotelCallback 酒店静态信息变更通知接收异常，hotelList null ： "+result);
            return new ResultMt<>("hotelList null",-1);
        }
        List<Long> updateDetailHotelIds = new ArrayList<>();
        List<String> updateHotelUpIds = new ArrayList<>();
        List<String> updateStateDownHotelIds = new ArrayList<>();
        for (MtHotelInfoStatusContentCallbackVo info:hotelData.getHotelList()){
            Long hotelId = info.getHotelId();
            //对比缓存校验是否售卖房型
            Boolean existSaleHotel = redisService.isMember(CommonConstants.SWITCH_SALE_HOTEL_TO_PRICE_LIST,hotelId.intValue());
            if(existSaleHotel){
                log.info("/////////////////  hotelCallback 存在符合的美团酒店上下线信息hotelId={}",hotelId);
                //遍历酒店
                Integer stateType = info.getType();
                if(1==stateType || 3==stateType){
                    //1  酒店信息发送变化 3 ;酒店上线
                    updateDetailHotelIds.add(info.getHotelId());
                    if(3==stateType){
                        updateHotelUpIds.add(String.valueOf(info.getHotelId()));
                    }
                }else if(2==stateType){
                    //酒店下线，更新数据库酒店信息状态为 state=0 异常
                    updateStateDownHotelIds.add(String.valueOf(info.getHotelId()));
                }
            }
        }
        if(updateDetailHotelIds.size()>0){
            //酒店推送频率不高，暂不考虑缓存队列

            //调用查询酒店详情
            /*Result<Object> detailGetResp = mtHotelService.getMtHotelDetail(updateDetailHotelIds);
            if(CommonConstants.SUCCESS==detailGetResp.getCode()){
                //接口返回成功，调用更新保存酒店详情（更新redis）
                Map<String,List<MtHotelDetailVo>> redisHotelInfoMap = new HashMap<>();
                List<MtHotelDetailVo> list = (List<MtHotelDetailVo>)detailGetResp.getData();
                if(null != list && list.size()>0){
                    redisHotelInfoMap.put(UUID.randomUUID().toString(),list);
                    Result<Object> saveResp = mtHotelService.saveHotelInfos(redisHotelInfoMap);
                    if(CommonConstants.SUCCESS!=saveResp.getCode()){
                        //保存失败，打印日志
                        log.error("//////////////////////// hotelCallback  stateType=1 酒店详情更新保存失败：{},{}",JSON.toJSONString(saveResp),JSON.toJSONString(list));
                    }
                }else{
                    log.error("//////////////////////// hotelCallback  stateType=1 酒店详情更新保存失败,订单详情获取为空：{},",JSON.toJSONString(list));
                }
            }else{
                //重新获取更新酒店详情失败，打印失败日志
                log.error("//////////////////////// hotelCallback  stateType=1 重新获取更新酒店详情失败：{},{}",JSON.toJSONString(detailGetResp),JSON.toJSONString(updateDetailHotelIds));
            }*/
        }
        if(updateHotelUpIds.size()>0){
            log.info("/////////////////  hotelCallback 存在符合的美团酒店上线信息当前result={},updateHotelUpIds={}",updateHotelUpIds);
            SendUtils.dingMsgNotLog("[CALLBACK-HOTEL-UP] 美团酒店上线推送 ", hotel.base.oversea.utils.DateUtil.getCurrTime()+"：酒店ID："+ JSON.toJSONString(updateHotelUpIds), MessageEnums.genre.GOODS_STATUS_AND_PRICE.getCode(),restTemplate);
            for (String id:updateHotelUpIds){

                //通知携程
                String res = requestSwitchsUpdateHotel(Integer.valueOf(id),1);

                //stateType=0 下线，更新数据库酒店信息,保存日志
                try {
                    MtHotelDetail mtHotelDetail = new MtHotelDetail();
                    mtHotelDetail.setMtHotelId(id);
                    mtHotelDetail.setMtStatusType(1);//酒店上下线，默认上线1  下线 0
                    mtHotelDetail.setRemark(result+"|api:"+res);//上游推送
                    mtHotelService.updateStateTypeByHotelId(mtHotelDetail);
                }catch (Exception e){
                    log.error("存在符合的美团酒店上线信息当前result 处理失败："+e.getMessage());
                    e.printStackTrace();
                }

            }

        }
        if(updateStateDownHotelIds.size()>0){
            log.info("/////////////////  hotelCallback 存在符合的美团酒店下线信息当前result={},updateStateDownHotelIds={}",result,updateStateDownHotelIds);
            SendUtils.dingMsgNotLog("[CALLBACK-HOTEL-DOWN] 美团酒店下线了 ", hotel.base.oversea.utils.DateUtil.getCurrTime()+"：酒店ID："+ JSON.toJSONString(updateStateDownHotelIds), MessageEnums.genre.GOODS_STATUS_AND_PRICE.getCode(),restTemplate);
            //String idsStr = "'"+updateStateDownHotelIds.stream().collect(Collectors.joining(",'"))+"'";
            for (String id:updateStateDownHotelIds){

                String swResult = requestSwitchsUpdateHotel(Integer.valueOf(id),0);

                redisService.remove(CommonConstants.SWITCH_MT_HOTEL_DETAIL_INFO_DATA_JOB_PUSH+id);
                redisService.remove(CommonConstants.SWITCH_MT_ONE_HOTEL_ROOMS_REDIS+id);
                redisService.remove(CommonConstants.SWITCH_MT_HOTEL_RP_GOODS_INFO_DATA_JOB_PUSH+id);

                try {
                    MtHotelDetail mtHotelDetail = new MtHotelDetail();
                    mtHotelDetail.setMtHotelId(id);
                    mtHotelDetail.setMtStatusType(0); //酒店上下线，默认上线1  下线 0
                    mtHotelDetail.setRemark(result+"|api:"+swResult);//上游推送
                    mtHotelService.updateStateTypeByHotelId(mtHotelDetail);
                }catch (Exception e){
                    log.error("存在符合的美团酒店下线信息当前result 处理失败："+e.getMessage());
                    e.printStackTrace();
                }
                //通知携程

            }
        }

        //返回上游
        return new ResultMt();
    }

    public String requestSwitchsUpdateHotel(Integer mtHotelId,Integer status){
        //发起请求
        Map map = new HashMap();
        map.put("mtHotelId",mtHotelId);
        map.put("status",status);//状态 0 下线 1 上线
        log.info("requestSwitchsUpdateHotel请求="+ JSON.toJSONString(map));
        Result result = RestTemplateUtils.post(CommonUrlConstants.SWITCHS_ONLINE_HOST+"/switchCreateRoom/downHotel", JSON.toJSONString(map),restTemplate);
        if(result.getCode()!= CommonConstants.SUCCESS){
            log.error("酒店推送变更 调用携程修改接口失败="+ JSON.toJSONString(result)+",请求参数："+ JSON.toJSONString(map));
            SendUtils.dingMsg("[CALLBACK-HOTEL]酒店推送变更，调用携程修改接口失败 ","请求参数："+ JSON.toJSONString(map)+" 响应："+ JSON.toJSONString(result), MessageEnums.genre.GOODS_STATUS_AND_PRICE.getCode(),restTemplate);
        }else{
            log.info("requestSwitchsUpdateHotel响应="+ JSON.toJSONString(result)+",请求参数："+ JSON.toJSONString(map));
        }
        return JSON.toJSONString(result);

    }
    /**
     * result内容为多层数据集合，返回str，外部parse对象获取数据
     * @param request
     * @return
     */
    private String getStrRequest(HttpServletRequest request){
        String type = request.getContentType();
        Map<String,Object> receiveMap = new HashMap<>();
        if("application/x-www-form-urlencoded".equals(type)){
            Enumeration<String> enu = request.getParameterNames();
            while (enu.hasMoreElements()) {
                String key = String.valueOf(enu.nextElement());
                String value = request.getParameter(key);
                receiveMap.put(key, value);
                return JSON.toJSONString(receiveMap);
            }
        }else{	//else是text/plain、application/json这两种情况
            BufferedReader reader = null;
            StringBuilder sb = new StringBuilder();
            try{
                reader = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
                String line = null;
                while ((line = reader.readLine()) != null){
                    sb.append(line);
                }
            } catch (IOException e){
                e.printStackTrace();
            } finally {
                try{
                    if (null != reader){
                        reader.close();
                    }
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
            String str = sb.toString();
            return str;
        }
        return null;
    }
    @PostMapping("/createTableJob")
    @ApiOperation(value = "创建隔天异步通知表",notes="必须经过auth授权")
    public Result<Object> createTableJob(){
        //生产隔天表
        String nowDate = hotel.base.oversea.utils.DateUtil.formatDate(hotel.base.oversea.utils.DateUtil.getNextDays(1),"yyyyMMdd");
        mtHotelOrderNotifyCallbackService.createTableJobByDate(nowDate);
        return new Result<>(CommonConstants.SUCCESS);
    }

}
